package servlet;

import it.polimi.swimv2.entities.Suggestion;
import it.polimi.swimv2.exception.AbilityExistsException;
import it.polimi.swimv2.exception.SuggestionException;
import it.polimi.swimv2.remote.SuggestionManagerRemote;
import it.polimi.swimv2.util.RemoteBindingName;

import java.io.IOException;
import java.util.Collection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class SuggestionServlet
 */
public class SuggestionServlet extends HttpServlet {	
	
	private static final String SESSION_ADMIN = "admin";
	private static final String SESSION_USERNAME = "user";
	// Page references:
	private static final String SUGGEST_ABILITY_JSP = "suggestAbility.jsp";
	private static final String MANAGE_SUGGESTION_JSP = "manageSuggestion.jsp";
	private static final String INDEX_JSP = "index.jsp";
	private static final String ERROR_JSP = "error.jsp";
	private static final String LOGIN_FORM_JSP = "loginForm.jsp";
	// Actions performed by this servlet:
	private static final String SHOW_SUGGEST_ABILITY_ACT = "showSuggestAbility";
	private static final String SHOW_MANAGE_SUGGESTION_ACT = "showManageSuggestion";
	private static final String ACCEPT_SUGGESTION_ACT = "acceptSuggestion";
	private static final String REFUSE_SUGGESTION_ACT = "refuseSuggestion";
	private static final String SEND_SUGGESTION_ACT = "sendSuggestion";
	// Parameters in HttpRequest:
	private static final String ACT = "act";
	private static final String SUGGESTION_ID_REQPARAM = "suggestionId";// String
	private static final String ABILITY_NAME_REQPARAM = "newAbility";// String
	private static final String SUGGESTIONS_REQPARAM = "suggestions";// Collection<Suggestion>
	// Error messages
	private static final String NO_ERROR = "noError";
	private static final String ALREADY_EXIST = "alreadyExists";
	private static final String SUGGEST_ERROR = "suggestError";
	private static final String NOT_VALID_ABILITY = "notValidAbility";
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public SuggestionServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		chooseAction(request, response);

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		chooseAction(request, response);
	}
	/**
	 * manages the action requested by http request
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void chooseAction(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		String actParam = request.getParameter(ACT);
		HttpSession session = request.getSession();
		if (actParam == null) {
			redirectToHome(response);
			return;
		}
		
		String username = (String) session.getAttribute(SESSION_USERNAME);
		if(username!=null){		
			if (actParam.equals(SHOW_SUGGEST_ABILITY_ACT)) {
					showSuggestAbility(request, response);
			}else if (actParam.equals(SEND_SUGGESTION_ACT)) {
				processSendSuggestion(request, response);
			}else {
				redirectToHome(response);
				
			}
			return;
		}
		String adminUsername = (String) session.getAttribute(SESSION_ADMIN);
		if(adminUsername!=null){
				if (actParam.equals(SHOW_MANAGE_SUGGESTION_ACT)) {
					showManageSuggestion(request, response);
				} else if (actParam.equals(ACCEPT_SUGGESTION_ACT)) {
					processAcceptSuggestion(request, response);
				} else if (actParam.equals(REFUSE_SUGGESTION_ACT)) {
					processRefuseSuggestion(request, response);
				}else {
					redirectToHome(response);
					
				}
				return;
		}
		response.sendRedirect(LOGIN_FORM_JSP);
		return;
	}
	/**
	 * shows the ability suggestion form
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void showSuggestAbility(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		RequestDispatcher dispatcher = request.getRequestDispatcher(SUGGEST_ABILITY_JSP);
		dispatcher.forward(request, response);

	}
	/**
	 * shows the ability suggestion list
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showManageSuggestion(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			SuggestionManagerRemote rem = retrieveSuggestionManagerRemote();
			Collection<Suggestion> suggestions = rem.getSuggestion();
			request.setAttribute(SUGGESTIONS_REQPARAM, suggestions);
			RequestDispatcher dispatcher = request
					.getRequestDispatcher(MANAGE_SUGGESTION_JSP);
			dispatcher.forward(request, response);
		} catch (NamingException e) {
			redirectToError(response);
		}

	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processRefuseSuggestion(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			SuggestionManagerRemote rem = retrieveSuggestionManagerRemote();
			String suggestionID = request.getParameter(SUGGESTION_ID_REQPARAM);
			if (suggestionID != null) {

				rem.refuseSuggestion(Integer.parseInt(suggestionID));
				showManageSuggestion(request, response);
			}
		} catch (NamingException e) {
			redirectToError(response);
		} catch (NumberFormatException e) {
			redirectToError(response);
		}

	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processAcceptSuggestion(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			SuggestionManagerRemote rem = retrieveSuggestionManagerRemote();
			String suggestionID = request.getParameter(SUGGESTION_ID_REQPARAM);
			if (suggestionID != null) {
				rem.acceptSuggestion(Integer.parseInt(suggestionID));
				showManageSuggestion(request, response);
			}
		} catch (NamingException e) {
			redirectToError(response);
		} catch (NumberFormatException e) {
			redirectToError(response);
		}

	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void processSendSuggestion(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		
		HttpSession session = request.getSession();
		String username = (String) session.getAttribute(SESSION_USERNAME);
		try {
			SuggestionManagerRemote rem = retrieveSuggestionManagerRemote();
			session = request.getSession();
			username = (String) session.getAttribute(SESSION_USERNAME);
			String newAbility = request.getParameter(ABILITY_NAME_REQPARAM);
			rem.sendSuggestion(username, newAbility);
			request.setAttribute(SUGGEST_ERROR, NO_ERROR);
			showSuggestAbility(request, response);
			return;
		} catch (NamingException e) {
			redirectToError(response);
		} catch (SuggestionException e) {
			request.setAttribute(SUGGEST_ERROR, NOT_VALID_ABILITY);
			showSuggestAbility(request, response);
		} catch (AbilityExistsException e) {
			request.setAttribute(SUGGEST_ERROR, ALREADY_EXIST);
			showSuggestAbility(request, response);
		}
	}
	/**
	 * 
	 * @param response
	 * @throws IOException
	 */
	private void redirectToHome(HttpServletResponse response)
			throws IOException {
		response.sendRedirect(INDEX_JSP);
	}
	/**
	 * 
	 * @param response
	 * @throws IOException
	 */
	private void redirectToError(HttpServletResponse response)
			throws IOException {
		response.sendRedirect(ERROR_JSP);

	}

	private SuggestionManagerRemote retrieveSuggestionManagerRemote()
			throws NamingException {
		Context jndiContext = new InitialContext();
		Object ref = jndiContext.lookup(RemoteBindingName.SUGGESTION_MANAGER);
		SuggestionManagerRemote rem = (SuggestionManagerRemote) ref;
		return rem;
	}
}
